﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ESRI.ArcGIS.Analyst3D;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.DataSourcesRaster;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using FRS.ExceptionLog;
using System.Runtime.InteropServices;

#region 一些必要的解释
// AxSceneControl控件实际上是在ESRI.ArcGIS.AxControls.dll中;
// AxSceneControl.Scene在ESRI.ArcGIS.3DAnalyst.dll中;
#endregion
namespace FRS.EsriExtension
{
    public static class AxSceneControlExtension
    {
        #region 加载文件
        /// <summary>
        /// 加载空间数据库
        /// @Author：CSDN.niewzh【https://blog.csdn.net/ScapeD】
        /// @Address：ArcGIS Engine打开文件地理数据库【https://blog.csdn.net/ScapeD/article/details/83751628?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-10.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-10.control】
        /// </summary>
        /// <param name="axSceneControl">调用对象</param>
        /// <param name="geodatabasePath">空间数据库路径【默认值为NULL表示调用者希望调用文件资源管理器打开】</param>
        public static void LoadGeodatabase(this AxSceneControl axSceneControl, string geodatabasePath = null)
        {
            //文件地理数据库本身数据以文件形式存储，没有像shp那种类型的指定文件，因此以打开文件夹的格式打开
            #region 如何理解下面的代码？
            // 由于C#和其他高级编程语言一样，对逻辑运算有“懒惰算法”，所以当我们确定“路径”非空时可以直接让其自赋值；
            // 如果“路径”是空值，意味着调用者需要利用“文件资源管理器”，当“用户”选择OK时才能将“路径”赋值为用户选择的路径；
            // 但是如果用户点击的按钮不是“OK”，则仍然自赋值（此时为NULL）
            #endregion
            FolderBrowserDialog dlg = new FolderBrowserDialog();
            geodatabasePath =
                (geodatabasePath != null) || (dlg.ShowDialog() == DialogResult.OK)
                ? geodatabasePath : dlg.SelectedPath;

            if (geodatabasePath == null)
            {

                MessageBox.Show("你没有选择任何GDB文件");
                return;
            }
            else
            {
                try
                {
                    IWorkspaceFactory pWorkspaceFactory = new FileGDBWorkspaceFactoryClass();
                    IWorkspace pworkspace = pWorkspaceFactory.OpenFromFile(geodatabasePath, 0);

                    axSceneControl.AddAllDataset(pworkspace);
                    return;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("文件打开失败\n" + geodatabasePath);
                    ExceptionLogRecorder.WriteExceptionLog(ex, "文件打开失败：" + geodatabasePath);
                    return;
                }
            }
        }
        /// <summary>
        /// 根据数据类型不同加载数据
        /// </summary>
        /// <param name="axSceneControl">调用对象</param>
        /// <param name="pWorkspace">工作空间【通过工作空间工厂从文件打开】</param>
        private static void AddAllDataset(this AxSceneControl axSceneControl, IWorkspace pWorkspace)
        {
            //数据集枚举，加载各种类型的数据
            IEnumDataset pEnumDataset = pWorkspace.get_Datasets(esriDatasetType.esriDTAny);
            //将IEnumDataset读到Dataset当中
            IDataset pDataset = pEnumDataset.Next();

            #region 要素数据集、要素类、栅格数据集【while (pDataset != null)】
            while (pDataset != null)
            {
                #region if (pDataset is IFeatureDataset) 如果是要素数据集
                if (pDataset is IFeatureDataset)  //要素数据集
                {
                    IFeatureWorkspace pFeatureworkspace = (IFeatureWorkspace)pWorkspace;
                    IFeatureDataset pFeatureDataset = pFeatureworkspace.OpenFeatureDataset(pDataset.Name);

                    IEnumDataset pEnumDataset1 = pFeatureDataset.Subsets;  //获取要素集合
                    IDataset pDataset1 = pEnumDataset1.Next();

                    while (pDataset1 != null)
                    {
                        if (pDataset1 is IFeatureClass)  //要素类
                        {
                            IFeatureLayer pFeatureLayer = new FeatureLayer();
                            pFeatureLayer.FeatureClass = pFeatureworkspace.OpenFeatureClass(pDataset1.Name);
                            pFeatureLayer.Name = pFeatureLayer.FeatureClass.AliasName;
                            if (pFeatureLayer.FeatureClass != null)
                            {
                                axSceneControl.Scene.AddLayer(pFeatureLayer);
                            }
                        }
                        pDataset1 = pEnumDataset1.Next();
                    }
                }
                #endregion
                #region else if (pDataset is IFeatureClass)  如果是要素类
                else if (pDataset is IFeatureClass)  //要素类
                {
                    IFeatureWorkspace pFeatureworkspace = pWorkspace as IFeatureWorkspace;
                    IFeatureLayer pFlyr = new FeatureLayer();
                    pFlyr.FeatureClass = pFeatureworkspace.OpenFeatureClass(pDataset.Name);
                    pFlyr.Name = pDataset.Name;
                    if (pFlyr != null)
                    {
                        axSceneControl.Scene.AddLayer(pFlyr);
                    }
                }
                #endregion
                #region else if (pDataset is IRasterDataset) 如果是栅格数据集
                else if (pDataset is IRasterDataset)  //栅格数据集
                {
                    IRasterWorkspaceEx pRasterworkspace = pWorkspace as IRasterWorkspaceEx;  //转为栅格空间
                    IRasterDataset pRasterDataset = pRasterworkspace.OpenRasterDataset(pDataset.Name);
                    if (pRasterDataset != null)
                    {
                        IRasterLayer pRasterLayer = new RasterLayer();
                        pRasterLayer.CreateFromDataset(pRasterDataset);
                        pRasterLayer.Name = pDataset.Name;
                        axSceneControl.Scene.AddLayer(pRasterLayer);
                    }
                }
                #endregion
                // 将枚举类型后移一位
                pDataset = pEnumDataset.Next();
            }
            #endregion
        }
        #endregion

        #region 添加各种类型的数据
        /// <summary>
        /// 添加Tin数据进入调用对象AxSceneControl中【将生成的TIN数据加载显示】
        /// </summary>
        /// <param name="axSceneControl">调用对象</param>
        /// <param name="tinFilePath">Tin数据的路径</param>
        public static ITinLayer AddTinData(this AxSceneControl axSceneControl, string tinFilePath)
        {
            IWorkspaceFactory pWSF = new TinWorkspaceFactory();
            ITinWorkspace TinWS = null;
            ITin tin = null;
            ITinLayer tinlayer = null;

            FileInfo fileinfo = new FileInfo(tinFilePath);
            if (pWSF.IsWorkspace(fileinfo.DirectoryName))
            {
                TinWS = pWSF.OpenFromFile(fileinfo.DirectoryName, 0) as ITinWorkspace;
                tin = TinWS.OpenTin(fileinfo.Name);
                tinlayer = new TinLayerClass();
                tinlayer.Dataset = tin;
                ILayer layer = tinlayer as ILayer;
                axSceneControl.Scene.AddLayer(layer, true);
                axSceneControl.SceneGraph.RefreshViewers();
            }
            return tinlayer;
        }
        /// <summary>
        /// 添加Shp数据进入调用对象AxSceneControl中【shpfile -> featureclass -> featurelayer -> scenecontrol】
        /// 通常情况下featureLayer.name = featureClass.name;
        /// </summary>
        /// <param name="axSceneControl">调用对象</param>
        /// <param name="shpFilepath">Shp数据的路径</param>
        public static IFeatureLayer AddShpData(this AxSceneControl axSceneControl, string shpFilepath)
        {
            string path = null;
            string filname = null;
            FileInfo fileinfo = null;
            IFeatureLayer pFeatureLayer = null;
            IFeatureClass pFeatureClass = null;

            fileinfo = new FileInfo(shpFilepath);
            path = fileinfo.DirectoryName;
            filname = System.IO.Path.GetFileName(shpFilepath);
            try
            {
                // 通过打开的Shp文件获取其FeatureClass
                IWorkspaceFactory pWSF = new ShapefileWorkspaceFactory();
                IWorkspace pWS = pWSF.OpenFromFile(path, 0);
                IFeatureWorkspace pFWS = pWS as IFeatureWorkspace;
                pFeatureClass = pFWS.OpenFeatureClass(filname);

                // 设置FeatureLayer的FeatureClass，然后将图层添加如SceneControl中
                pFeatureLayer = new FeatureLayerClass();
                pFeatureLayer.FeatureClass = pFeatureClass;
                pFeatureLayer.Name = pFeatureClass.AliasName;
                axSceneControl.Scene.AddLayer(pFeatureLayer as ILayer, false);

                return pFeatureLayer;
            }
            catch (FileNotFoundException ex)
            {
                // 应该调用日志记录的类：记录文件打开失败。
                ExceptionLogRecorder.WriteExceptionLog(ex, "shp文件打开失败！\n文件名为：" + fileinfo.FullName + "可能并不存在于磁盘中");
                return pFeatureLayer;
            }
        }
        /// <summary>
        /// 添加DEM数据【将栅格影像数据添加至axSceneControl中】
        /// </summary>
        /// <param name="axSceneControl">调用对象</param>
        /// <param name="demFilePath">用户选择的dem数据的路径</param>
        public static IRasterLayer AddDemData(this AxSceneControl axSceneControl, string demFilePath)
        {
            #region 获取Dem图层
            ILayer layer;
            IRasterLayer rasterLayer = null;
            IWorkspaceFactory rasterWorkspaceFactory = new RasterWorkspaceFactoryClass();
            IRasterWorkspace rasterWorkspace;
            FileInfo file = new FileInfo(demFilePath);
            if (rasterWorkspaceFactory.IsWorkspace(file.DirectoryName))
            {
                rasterWorkspace = rasterWorkspaceFactory.OpenFromFile(file.DirectoryName, 0) as IRasterWorkspace;
                IRasterDataset rasterDataset = rasterWorkspace.OpenRasterDataset(file.Name);
                rasterLayer = new RasterLayerClass();
                rasterLayer.CreateFromDataset(rasterDataset);
            }
            layer = rasterLayer as ILayer;
            #endregion

            #region 向axSceneControl中添加dem图层
            ISceneGraph pSceneGraph = axSceneControl.SceneGraph;
            pSceneGraph.Scene.AddLayer(layer);
            pSceneGraph.RefreshViewers();
            return rasterLayer;
            #endregion
        }
        #endregion

        #region 为GeoFeatureLayer设置3D符号
        #region 单一渲染
        /// <summary>
        /// 单一渲染：为某一个图层3D渲染
        /// </summary>
        /// <param name="axSceneControl">调用对象</param>
        /// <param name="pGeoFeatureLayer"></param>
        /// <param name="marker3DSymbolFilePath">某一个图层</param>
        /// <param name="sizeRendererExpression">符号的文件位置</param>
        public static void Set3DSymbol_Single(this AxSceneControl axSceneControl, IGeoFeatureLayer pGeoFeatureLayer, string marker3DSymbolFilePath, string sizeRendererExpression)
        {
            axSceneControl.MousePointer = ESRI.ArcGIS.Controls.esriControlsMousePointer.esriPointerHourglass;

            pGeoFeatureLayer.Set3DSymbol_Single(marker3DSymbolFilePath, sizeRendererExpression);
            axSceneControl.SceneGraph.Invalidate(pGeoFeatureLayer, true, true);
            axSceneControl.SceneGraph.RefreshViewers();

            axSceneControl.MousePointer = ESRI.ArcGIS.Controls.esriControlsMousePointer.esriPointerDefault;
        }
        /// <summary>
        /// 单一渲染：为某一个图层3D渲染【图层通过索引号得到】
        /// </summary>
        /// <param name="axSceneControl">调用对象</param>
        /// <param name="layerOrder">图层的索引号</param>
        /// <param name="marker3DSymbolFilePath">3D符号的文件位置</param>
        public static void Set3DSymbol_Single(this AxSceneControl axSceneControl, int layerOrder, string marker3DSymbolFilePath, string sizeRendererExpression)
        {
            IGeoFeatureLayer pGeoFeatureLayer = axSceneControl.Scene.get_Layer(layerOrder) as IGeoFeatureLayer;
            axSceneControl.Set3DSymbol_Single(pGeoFeatureLayer, marker3DSymbolFilePath, sizeRendererExpression);
        }
        /// <summary>
        /// 单一渲染：为某一个图层3D渲染【图层通过它的名字得到】
        /// </summary>
        /// <param name="axSceneControl">调用对象</param>
        /// <param name="layerName">图层的名字</param>
        /// <param name="marker3DSymbolFilePath">3D符号的文件位置</param>
        public static void Set3DSymbol_Single(this AxSceneControl axSceneControl, string layerName, string marker3DSymbolFilePath, string sizeRendererExpression)
        {
            IGeoFeatureLayer pGeoFeatureLayer = axSceneControl.GetLayerByName(layerName, "IGeoFeatureLayer") as IGeoFeatureLayer;
            axSceneControl.Set3DSymbol_Single(pGeoFeatureLayer, marker3DSymbolFilePath, sizeRendererExpression);
        }
        #endregion
        #region 唯一值渲染


        /// <summary>
        /// 设置3D样式(不将图层进行分割)【对某个字段进行唯一值渲染，同时依据某个表达式设置样式的大小】
        /// </summary>
        /// <param name="axSceneControl">调用对象【强制刷新所用】</param>
        /// <param name="pGeoFeatureLayer">对哪个图层渲染</param>
        /// <param name="uniqueValueField">对哪个字段进行唯一值渲染</param>
        /// <param name="value_filePath">所有唯一值对应的样式模型(文件的位置)</param>
        /// <param name="sizeRendererExpression">设置大小的表达式</param>
        /// <returns>是否设置成功</returns>
        public static bool Set3DSymbol_UniqueWithoutSplitLayer(this AxSceneControl axSceneControl, IGeoFeatureLayer pGeoFeatureLayer, string uniqueValueField, Dictionary<string, string> value_filePath, string sizeRendererExpression)
        {
            axSceneControl.MousePointer = ESRI.ArcGIS.Controls.esriControlsMousePointer.esriPointerHourglass;

            // 给系统栈留点空间吧，快挤死了
            bool result = pGeoFeatureLayer.Set3DSymbol_UniqueWithoutSplitLayer(uniqueValueField, value_filePath, sizeRendererExpression);
            // 强制刷新
            axSceneControl.SceneGraph.Invalidate(pGeoFeatureLayer, true, true);
            axSceneControl.SceneGraph.RefreshViewers();

            axSceneControl.MousePointer = ESRI.ArcGIS.Controls.esriControlsMousePointer.esriPointerDefault;
            return result;
        }
        /// <summary>
        /// 设置3D样式(不将图层进行分割)【对某个字段进行唯一值渲染，同时依据某个表达式设置样式的大小】
        /// </summary>
        /// <param name="axSceneControl">调用对象【强制刷新所用】</param>
        /// <param name="layerOder">图层的编号</param>
        /// <param name="uniqueValueField">对哪个字段进行唯一值渲染</param>
        /// <param name="value_filePath">所有唯一值对应的样式模型(文件的位置)</param>
        /// <param name="sizeRendererExpression">设置大小的表达式</param>
        /// <returns>是否设置成功</returns>
        public static bool Set3DSymbol_UniqueWithoutSplitLayer(this AxSceneControl axSceneControl, int layerOder, string uniqueValueField, Dictionary<string, string> value_filePath, string sizeRendererExpression)
        {
            IGeoFeatureLayer pGeoFeatureLayer = axSceneControl.Scene.get_Layer(layerOder) as IGeoFeatureLayer;
            bool result = axSceneControl.Set3DSymbol_UniqueWithoutSplitLayer(pGeoFeatureLayer, uniqueValueField, value_filePath, sizeRendererExpression);
            return result;
        }
        /// <summary>
        /// 设置3D样式(不将图层进行分割)【对某个字段进行唯一值渲染，同时依据某个表达式设置样式的大小】
        /// </summary>
        /// <param name="axSceneControl">调用对象【强制刷新所用】</param>
        /// <param name="layerName">图层的名称</param>
        /// <param name="uniqueValueField">对哪个字段进行唯一值渲染</param>
        /// <param name="value_filePath">所有唯一值对应的样式模型(文件的位置)</param>
        /// <param name="sizeRendererExpression">设置大小的表达式</param>
        /// <returns>是否设置成功</returns>
        public static bool Set3DSymbol_UniqueWithoutSplitLayer(this AxSceneControl axSceneControl, string layerName, string uniqueValueField, Dictionary<string, string> value_filePath, string sizeRendererExpression)
        {
            IGeoFeatureLayer pGeoFeatureLayer = axSceneControl.GetLayerByName(layerName, "IGeoFeatureLayer") as IGeoFeatureLayer;
            bool result = axSceneControl.Set3DSymbol_UniqueWithoutSplitLayer(pGeoFeatureLayer, uniqueValueField, value_filePath, sizeRendererExpression);
            return result;
        }

        /// <summary>
        /// 更新某个图层中某个唯一值的3D样式
        /// <para>@Tips: 不是字段名而是唯一值！</para>
        /// </summary>
        /// <param name="axSceneControl">调用对象</param>
        /// <param name="pGeoFeatureLayer">哪个图层</param>
        /// <param name="uniqueValue">哪个唯一值【不是字段名而是唯一值】</param>
        /// <param name="marker3DSymbolFilePath">3D模型路径</param>
        /// <returns>是否更改成功</returns>
        public static bool Update3DSymbol(this AxSceneControl axSceneControl, IGeoFeatureLayer pGeoFeatureLayer, string uniqueValue, string marker3DSymbolFilePath)
        {
            axSceneControl.MousePointer = ESRI.ArcGIS.Controls.esriControlsMousePointer.esriPointerHourglass;

            // 给系统栈留点空间吧，快挤死了
            bool result = pGeoFeatureLayer.Update3DSymbol(uniqueValue, marker3DSymbolFilePath);
            // 强制刷新
            axSceneControl.SceneGraph.Invalidate(pGeoFeatureLayer, true, true);
            axSceneControl.SceneGraph.RefreshViewers();

            axSceneControl.MousePointer = ESRI.ArcGIS.Controls.esriControlsMousePointer.esriPointerDefault;
            return result;
        }
        /// <summary>
        /// 更新某个图层中某个唯一值的3D样式
        /// <para>@Tips: 不是字段名而是唯一值！</para>
        /// </summary>
        /// <param name="axSceneControl">调用对象</param>
        /// <param name="layerOder">图层编号</param>
        /// <param name="uniqueValue">哪个唯一值【不是字段名而是唯一值】</param>
        /// <param name="marker3DSymbolFilePath">3D模型路径</param>
        /// <returns>是否更改成功</returns>
        public static bool Update3DSymbol(this AxSceneControl axSceneControl, int layerOder, string uniqueValue, string marker3DSymbolFilePath)
        {
            IGeoFeatureLayer pGeoFeatureLayer = axSceneControl.Scene.get_Layer(layerOder) as IGeoFeatureLayer;
            bool result = axSceneControl.Update3DSymbol(pGeoFeatureLayer, uniqueValue, marker3DSymbolFilePath);
            return result;
        }
        /// <summary>
        /// 更新某个图层中某个唯一值的3D样式
        /// <para>@Tips: 不是字段名而是唯一值！</para>
        /// </summary>
        /// <param name="axSceneControl">调用对象</param>
        /// <param name="layerName">图层名称</param>
        /// <param name="uniqueValue">哪个唯一值【不是字段名而是唯一值】</param>
        /// <param name="marker3DSymbolFilePath">3D模型路径</param>
        /// <returns>是否更改成功</returns>
        public static bool Update3DSymbol(this AxSceneControl axSceneControl, string layerName, string uniqueValue, string marker3DSymbolFilePath)
        {
            IGeoFeatureLayer pGeoFeatureLayer = axSceneControl.GetLayerByName(layerName, "IGeoFeatureLayer") as IGeoFeatureLayer;
            bool result = axSceneControl.Update3DSymbol(pGeoFeatureLayer, uniqueValue, marker3DSymbolFilePath);
            return result;
        }

        ///// <summary>
        ///// 唯一值渲染：为一个shp文件的某个字段进行分类【图层通过它的索引号得到】
        ///// </summary>
        ///// <param name="axSceneControl">调用对象</param>
        ///// <param name="layerOrder">图层的索引号</param>
        ///// <param name="uniqueValueField">唯一值字段</param>
        ///// <param name="value_filePath">字段值对应的3D模型文件路径</param>
        //public static void Set3DSymbol_Unique(this AxSceneControl axSceneControl, int layerOrder, string uniqueValueField, Dictionary<string, string> value_filePath)
        //{
        //    axSceneControl.MousePointer = ESRI.ArcGIS.Controls.esriControlsMousePointer.esriPointerHourglass;

        //    //获取目标图层，并获取到所有的唯一值
        //    IGeoFeatureLayer pGeoFeatLyr = axSceneControl.Scene.get_Layer(layerOrder) as IGeoFeatureLayer;
        //    List<string> uniqueValues = pGeoFeatLyr.GetUniqueValue(uniqueValueField);
        //    foreach (string value in uniqueValues)
        //    {
        //        IQueryFilter pQueryFilter = new QueryFilter();
        //        pQueryFilter.WhereClause = "Name=" + value;
        //        axSceneControl.SplitByAttribute(layerOrder, pQueryFilter, @"E:\Users\dsf\Desktop\新建文件夹\" + value + ".shp");
        //    }

        //    axSceneControl.MousePointer = ESRI.ArcGIS.Controls.esriControlsMousePointer.esriPointerDefault;
        //}
        #endregion
        #endregion
        #region 获取图层的函数
        /// <summary>
        /// 通过图层的名字得到图层【如果没有这个图层则抛出空指针异常】
        /// </summary>
        /// <param name="axSceneControl">调用对象</param>
        /// <param name="layerName">图层名称</param>
        /// <returns>所求图层</returns>
        public static ILayer GetLayerByName(this AxSceneControl axSceneControl, string layerName, string layerType)
        {
            ILayer retVal = null;
            #region 常用接口对应的UID号
            // {6CA416B1-E160-11D2-9F4E-00C04F6BC78E}   IDataLayer
            // {40A9E885-5533-11d0-98BE-00805F7CED21}   IFeatureLayer
            // {E156D7E5-22AF-11D3-9F99-00C04F6BC78E}   IGeoFeatureLayer
            // {34B2EF81-F4AC-11D1-A245-080009B6F22B}   IGraphicsLayer
            // {5CEAE408-4C0A-437F-9DB3-054D83919850}   IFDOGraphicsLayer
            // {0C22A4C7-DAFD-11D2-9F46-00C04F6BC78E}   ICoverageAnnotationLayer
            // {EDAD6644-1810-11D1-86AE-0000F8751720}   IGroupLayer
            // {D02371C7-35F7-11D2-B1F2-00C04F8EDEFF}   IRasterLayer
            #endregion
            #region 设置uid
            ESRI.ArcGIS.esriSystem.UID uid = new UIDClass();
            try
            {
                uid.Value = ConfigurationManager.AppSettings[layerType];
            }
            catch (Exception ex)
            {
                ExceptionLog.ExceptionLogRecorder.WriteExceptionLog(ex, string.Format("“{0}”不是一个预期范围中的值，获取图层失败", layerType));
                return null;
            }
            #endregion
            IEnumLayer enumLayer = axSceneControl.Scene.get_Layers(uid, true);
            enumLayer.Reset();
            ILayer layer = enumLayer.Next();

            while (layer != null)
            {
                if (layer.Name.ToString() == layerName)
                {
                    retVal = layer;
                    break;
                }
                layer = enumLayer.Next();
            }

            if (retVal == null)
            {
                string sceneName = axSceneControl.Scene.Name;
                throw (new NullReferenceException(string.Format("GetLayerByName: 在场景({0})中找不到指定名称({1})的图层", sceneName, layerName)));
            }

            return retVal;
        }
        /// <summary>
        /// 找到调用对象中第一个栅格图层【一般来说一个scene中也就只有一个raster图层】
        /// </summary>
        /// <param name="axSceneControl">调用对象</param>
        /// <returns>第一个栅格图层</returns>
        public static IRaster GetFirstRaster(this AxSceneControl axSceneControl)
        {
            IScene scene = axSceneControl.Scene;
            IRaster raster = null;
            for (int i = 0; i < scene.LayerCount; i++)
            {
                ILayer lyr = scene.get_Layer(i);
                if (lyr is IRasterLayer)
                {
                    IRasterLayer rLayer = lyr as IRasterLayer;
                    raster = rLayer.Raster;
                    break;
                }
            }

            if (raster == null)
            {
                string sceneName = axSceneControl.Scene.Name;
                throw (new NullReferenceException(string.Format("GetLayerByName: 在场景({0})中找不到栅格图层", sceneName)));
            }

            return raster;
        }
        #endregion

        #region 设置浮动
        public static void SetFloat()
        {

        }
        #endregion

        // 根据属性分割
        private static void SplitByAttribute(this AxSceneControl axSceneControl, int layerOrder, IQueryFilter pQueryFilter, string targetWorkspacePath)
        {
            // 源数据工作空间
            IFeatureClass pSourceFeatureClass = (axSceneControl.Scene.get_Layer(layerOrder) as IGeoFeatureLayer).FeatureClass;
            IDataset pSourceDataset = pSourceFeatureClass as IDataset;
            IFeatureClassName pSourceFeatureClassName = pSourceDataset.FullName as IFeatureClassName;
            IWorkspace pSourceWorkspace = pSourceDataset.Workspace;

            // 目标数据工作空间
            IWorkspaceFactory pTargetWorkspaceFactory = new ShapefileWorkspaceFactory();
            IWorkspace pTargetWorkspace = pTargetWorkspaceFactory.OpenFromFile(System.IO.Path.GetDirectoryName(targetWorkspacePath), 0);
            IDataset pTargetDataSet = pTargetWorkspace as IDataset;

            // 设置目标数据属性
            IWorkspaceName pTargetWorkspaceName = pTargetDataSet.FullName as IWorkspaceName;
            IFeatureClassName pTargetFeatureClassName = new FeatureClassName() as IFeatureClassName;
            IDatasetName pTargetDatasetName = pTargetFeatureClassName as IDatasetName;
            pTargetDatasetName.WorkspaceName = pTargetWorkspaceName;
            pTargetDatasetName.Name = System.IO.Path.GetFileName(targetWorkspacePath);

            // 检查字段
            IFieldChecker pFieldChecker = new FieldChecker();
            pFieldChecker.InputWorkspace = pSourceWorkspace;
            pFieldChecker.ValidateWorkspace = pTargetWorkspace;

            // 字段转换
            IFields pSourceFields = pSourceFeatureClass.Fields;
            IFields pTargetFields = null;
            IEnumFieldError pEnumFieldError = null;
            pFieldChecker.Validate(pSourceFields, out pEnumFieldError, out pTargetFields);

            // 数据转换
            IFeatureDataConverter pFeatureDataConverter = new FeatureDataConverter();
            pFeatureDataConverter.ConvertFeatureClass(pSourceFeatureClassName, pQueryFilter, null, pTargetFeatureClassName, null, pTargetFields, "", 1000, 0);
        }
    }
}